AFRAME.registerComponent('sky-map', {
  schema: {
    src: { default: '' },
    intensity: { default: 1 },
    child: { default: '*' },
    background: { default: false },
    roughness: { default: -1 },
    metalness: { default: -1 },
  },

  init() {
    const comps = Object.keys(this.el.components);
    if (comps.includes('gltf-model') || comps.includes('obj-model')) {
      // 3d models
      this.el.addEventListener('model-loaded', this.handleMesh.bind(this));
    } else {
      // primitive
      this.handleMesh();
    }
  },

  handleMesh() {
    const object3D = this.el.object3D;
    object3D.traverse(child => {
      if (child.type.toLowerCase() !== 'mesh') return;
      if (this.data.child === '*' || child.name.includes(this.data.child)) {
        const material = child.material;
        this.setEnvMap(material);
      }
    });
  },

  setEnvMap(material) {
    const texUrl = this.getEquirectangular();

    let targetCube;
    if (THREE.WebGLRenderTargetCube) {
      targetCube = new THREE.WebGLRenderTargetCube(128);
    } else {
      targetCube = new THREE.WebGLCubeRenderTarget(128);
    }

    const renderer = this.el.sceneEl.renderer;
    const texture = new THREE.TextureLoader().load(texUrl, (e) => {
      const cubeTex = targetCube.fromEquirectangularTexture(renderer, texture);
      material.envMap = cubeTex.texture;
      material.envMapIntensity = this.data.intensity;

      if (this.data.background) {
        this.el.sceneEl.object3D.background = cubeTex.texture;
      }

      const { roughness, metalness } = this.data;
      if (roughness !== -1) { material.roughness = roughness; }
      if (metalness !== -1) { material.metalness = metalness; }

      material.needsUpdate = true;
    });
  },

  getEquirectangular() {
    let result = this.getDefaultTexture();

    if (this.isURL(this.data.src)) {
      result = this.data.src;
    } else if (this.data.src.startsWith('#') || this.data.src.startsWith('.')) {
      const el = document.querySelector(this.data.src);
      if (el instanceof HTMLImageElement) {
        result = el.src;
      }
    }
    return result;
  },

  isURL(str) {
    var urlPattern =
      /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/;
    return urlPattern.test(str);
  },

  getDefaultTexture() {
    return '';
  },
});
